package com.easylinkin.linkappapi.machinery.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.common.utils.DateUtil;
import com.easylinkin.linkappapi.device.entity.Device;
import com.easylinkin.linkappapi.device.service.DeviceService;
import com.easylinkin.linkappapi.deviceunit.entity.DeviceUnit;
import com.easylinkin.linkappapi.deviceunit.service.DeviceUnitService;
import com.easylinkin.linkappapi.machinery.dto.MachineryIotDeviceDto;
import com.easylinkin.linkappapi.machinery.entity.TowerCraneCollisionAlarmRecord;
import com.easylinkin.linkappapi.machinery.entity.TowerCranePosition;
import com.easylinkin.linkappapi.machinery.mapper.TowerCraneCollisionAlarmRecordMapper;
import com.easylinkin.linkappapi.machinery.mapper.TowerCranePositionMapper;
import com.easylinkin.linkappapi.machinery.service.TowerCranePositionService;
import com.easylinkin.linkappapi.machinery.service.TowerCraneWorkRecordService;
import com.easylinkin.linkappapi.machinery.vo.CollisionAlarmRecordVO;
import com.easylinkin.linkappapi.machinery.vo.MachineryDeviceVo;
import com.easylinkin.linkappapi.machinery.vo.TowerCranePositionVO;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.shigongyun.service.MachineryMonitorBiService;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

/**
 * <p>
 * 塔吊在图纸上的位置 服务实现类
 * </p>
 *
 * @author Xiaoyang
 * @since 2022-11-21
 */
@Service
public class TowerCranePositionServiceImpl extends
    ServiceImpl<TowerCranePositionMapper, TowerCranePosition> implements TowerCranePositionService {

  @Resource
  private CommonService commonService;

  @Resource
  private LinkappUserContextProducer linkappUserContextProducer;

  @Resource
  private MachineryMonitorBiService machineryMonitorBiService;

  @Resource
  private TowerCraneCollisionAlarmRecordMapper towerCraneCollisionAlarmRecordMapper;

  @Resource
  private DeviceService deviceService;

  @Resource
  private DeviceUnitService deviceUnitService;

  @Resource
  private TowerCraneWorkRecordService workRecordService;

  @Override
  public List<TowerCranePositionVO> getListIncludeCollisionAlarmRecord() {
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    List<TowerCranePositionVO> towerCranePositions = selectAll();
    if (CollectionUtil.isNotEmpty(towerCranePositions)) {
      towerCranePositions.forEach(p -> {
        // 塔吊告警数据+塔吊实时数据
        Device device = new Device();
        device.setCode(p.getDeviceCode());
        List<Device> deviceList = deviceService.selectDevices(device);
        if (CollectionUtil.isNotEmpty(deviceList)) {
          device = deviceList.get(0);
          DeviceUnit deviceUnit = deviceUnitService.getById(device.getDeviceUnitId());
          if (null != deviceUnit) {
            p.setDeviceUnitVersion(deviceUnit.getVersion());
          }
          TowerCraneCollisionAlarmRecord realTimeData = workRecordService
              .selectTowerRealTimeData(device, p.getMachineryId());// 塔吊实时数据
          // 设置查询条件 获取该塔吊当日告警记录
          CollisionAlarmRecordVO towerCraneCollisionAlarmRecord = new CollisionAlarmRecordVO();
          towerCraneCollisionAlarmRecord.setTenantId(tenantId);
          towerCraneCollisionAlarmRecord.setMachineryId(p.getMachineryId());
          towerCraneCollisionAlarmRecord.setDeviceCode(p.getDeviceCode());
          towerCraneCollisionAlarmRecord
              .setStartTime(DateUtil.getYYYYMMDDHHMMSSDate(DateUtil.getCurrentDayMixDate()));
          towerCraneCollisionAlarmRecord
              .setEndTime(DateUtil.getYYYYMMDDHHMMSSDate(DateUtil.getCurrentDayMaxDate()));
          List<TowerCraneCollisionAlarmRecord> records = towerCraneCollisionAlarmRecordMapper
              .selectByMachinery(towerCraneCollisionAlarmRecord);
          TowerCraneCollisionAlarmRecord alarmRecord = new TowerCraneCollisionAlarmRecord();
          if (CollectionUtil.isNotEmpty(records)) {
            alarmRecord = records.get(0);// 获取告警数据
          }
          // 填充实时塔吊数据
          if (null != realTimeData) {
            alarmRecord.setDriverName1(realTimeData.getDriverName1());// 司机姓名
            alarmRecord.setHeight(realTimeData.getHeight());// 吊钩高度 单位m
            alarmRecord.setRange(realTimeData.getRange());// 回转幅度 单位m
            alarmRecord.setRotation(realTimeData.getRotation());// 回转 单位°
            alarmRecord.setCraneArmHeight(realTimeData.getCraneArmHeight());// 塔臂高 单位m
            alarmRecord.setCraneForeArmLength(realTimeData.getCraneForeArmLength());// 前臂长 单位m
            alarmRecord.setCraneRearArmLength(realTimeData.getCraneRearArmLength());// 后臂长 单位m
          }
          p.setAlarmRecord(alarmRecord);
        }
      });
    }
    return towerCranePositions;
  }

  @Override
  public List<TowerCranePositionVO> selectAll() {
    List<TowerCranePositionVO> result = new ArrayList<>();
    MachineryDeviceVo machineryDeviceVo = new MachineryDeviceVo();
    machineryDeviceVo.setTypeCode("QUIP_TSQZJ_01");
    List<MachineryIotDeviceDto> data = machineryMonitorBiService
        .selectMachineryAndDeviceByCondition(machineryDeviceVo);
    if (CollectionUtil.isNotEmpty(data)) {
      data.forEach(p -> {
        TowerCranePosition position = findByMachineryIdAndDeviceCode(p.getId(), p.getDeviceCode());
        if (null != position) {
          TowerCranePositionVO vo = new TowerCranePositionVO();
          BeanUtils.copyProperties(position, vo);
          vo.setName(p.getName());
          result.add(vo);
        }
      });
    }
    return result;
  }

  @Override
  public TowerCranePosition findByMachineryIdAndDeviceCode(Integer machineryId, String deviceCode) {
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    QueryWrapper<TowerCranePosition> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("tenant_id_", tenantId)
        .eq("machinery_id", machineryId)
        .eq("device_code", deviceCode);
    TowerCranePosition towerCranePosition = baseMapper.selectOne(queryWrapper);
    return towerCranePosition;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean saveAll(List<TowerCranePosition> positions) {
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    QueryWrapper<TowerCranePosition> qw = new QueryWrapper<>();
    qw.eq("tenant_id_", tenantId);
    baseMapper.delete(qw);
    for (TowerCranePosition towerCranePosition : positions) {
      commonService.setCreateAndModifyInfo(towerCranePosition);
      towerCranePosition.setTenantId(tenantId);
      validParamRequired(towerCranePosition);
      validRepeat(towerCranePosition);
      validParamFormat(towerCranePosition);
      save(towerCranePosition);
    }
    return true;
  }

  /**
   * 校验重复
   */
  private void validRepeat(TowerCranePosition position) {
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    QueryWrapper<TowerCranePosition> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("tenant_id_", tenantId)
        .eq("machinery_id", position.getMachineryId())
        .eq("device_code", position.getDeviceCode());
    List<TowerCranePosition> list = baseMapper.selectList(queryWrapper);
    if (list.size() > 0) {
      throw new BusinessException("设备编号有重复");
    }
  }


  /**
   * 校验参数必填
   */
  private void validParamRequired(TowerCranePosition position) {
    Assert.notNull(position, "参数为空");
    Assert.notNull(position.getPositionX(), "positionX 参数为空");
    Assert.notNull(position.getPositionY(), "positionX 参数为空");
    Assert.notNull(position.getMachineryId(), "machineryId 参数为空");
    Assert.notNull(position.getCircleRadius(), "circleRadius 参数为空");
    Assert.isTrue(StringUtils.isNotBlank(position.getDeviceCode()), "设备编号为空");
  }

  /**
   * 校验参数格式
   */
  private void validParamFormat(TowerCranePosition appDevicePosition) {
    Assert.isTrue(appDevicePosition.getDeviceCode() == null
            || appDevicePosition.getDeviceCode().length() <= 32,
        "名称超长");
  }
}
